/**
 * 位置选择和地图相关工具类
 * 提供完整的地图选择、定位、地址解析功能
 */

// 腾讯地图API配置
const TENCENT_MAP_CONFIG = {
  key: 'T23BZ-PTJRT-4GPX3-LI7MB-YOHKH-NSFAT', // 您的腾讯地图API Key
  baseUrl: 'https://apis.map.qq.com'
};

export interface LocationInfo {
  name: string;          // 位置名称
  address: string;       // 详细地址
  latitude: number;      // 纬度
  longitude: number;     // 经度
  province?: string;     // 省份
  city?: string;         // 城市
  district?: string;     // 区县
}

export interface GeocodeResult {
  address: string;       // 格式化地址
  province: string;      // 省份
  city: string;         // 城市
  district: string;     // 区县
  street: string;       // 街道
  streetNumber: string; // 门牌号
}

export class LocationHelper {
  
  /**
   * 选择位置（使用微信内置地图选择器）
   * @param options 选择选项
   * @returns Promise<LocationInfo>
   */
  static chooseLocation(options?: {
    latitude?: number;    // 初始位置纬度
    longitude?: number;   // 初始位置经度
  }): Promise<LocationInfo> {
    return new Promise((resolve, reject) => {
      // 首先检查位置权限
      wx.getSetting({
        success: (res) => {
          if (res.authSetting['scope.userLocation'] === false) {
            // 用户之前拒绝了位置权限
            wx.showModal({
              title: '位置权限',
              content: '需要获取您的位置信息来选择商家地址，请在设置中开启位置权限',
              confirmText: '去设置',
              success: (modalRes) => {
                if (modalRes.confirm) {
                  wx.openSetting({
                    success: (settingRes) => {
                      if (settingRes.authSetting['scope.userLocation']) {
                        // 权限开启成功，重新调用选择位置
                        this.doChooseLocation(options, resolve, reject);
                      } else {
                        reject(new Error('位置权限未开启'));
                      }
                    },
                    fail: () => reject(new Error('打开设置失败'))
                  });
                } else {
                  reject(new Error('用户取消授权'));
                }
              }
            });
          } else {
            // 有权限或未询问过，直接调用选择位置
            this.doChooseLocation(options, resolve, reject);
          }
        },
        fail: () => reject(new Error('获取设置失败'))
      });
    });
  }

  /**
   * 执行位置选择
   */
  private static doChooseLocation(
    options: any,
    resolve: (value: LocationInfo) => void,
    reject: (reason: any) => void
  ) {
    const chooseOptions: any = {
      success: (res: any) => {
        console.log('选择位置成功:', res);
        
        const locationInfo: LocationInfo = {
          name: res.name || '',
          address: res.address || '',
          latitude: res.latitude,
          longitude: res.longitude
        };
        
        resolve(locationInfo);
      },
      fail: (err: any) => {
        console.error('选择位置失败:', err);
        
        if (err.errMsg.includes('cancel')) {
          reject(new Error('用户取消选择'));
        } else if (err.errMsg.includes('auth deny')) {
          reject(new Error('位置权限被拒绝'));
        } else {
          reject(new Error('选择位置失败'));
        }
      }
    };

    // 如果提供了初始位置，设置地图中心点
    if (options?.latitude && options?.longitude) {
      chooseOptions.latitude = options.latitude;
      chooseOptions.longitude = options.longitude;
    }

    wx.chooseLocation(chooseOptions);
  }

  /**
   * 获取当前位置
   * @param highAccuracy 是否高精度定位
   * @returns Promise<LocationInfo>
   */
  static getCurrentLocation(highAccuracy: boolean = false): Promise<LocationInfo> {
    return new Promise((resolve, reject) => {
      wx.getLocation({
        type: 'gcj02',
        isHighAccuracy: highAccuracy,
        highAccuracyExpireTime: 4000,
        success: (res) => {
          console.log('获取当前位置成功:', res);
          
          // 通过逆地址解析获取地址信息
          this.reverseGeocode(res.latitude, res.longitude)
            .then((address) => {
              resolve({
                name: '当前位置',
                address: address,
                latitude: res.latitude,
                longitude: res.longitude
              });
            })
            .catch(() => {
              // 即使地址解析失败，也返回坐标信息
              resolve({
                name: '当前位置',
                address: `纬度:${res.latitude}, 经度:${res.longitude}`,
                latitude: res.latitude,
                longitude: res.longitude
              });
            });
        },
        fail: (err) => {
          console.error('获取当前位置失败:', err);
          
          if (err.errMsg.includes('auth deny')) {
            wx.showModal({
              title: '位置权限',
              content: '需要获取您的位置信息，请在设置中开启位置权限',
              confirmText: '去设置',
              success: (modalRes) => {
                if (modalRes.confirm) {
                  wx.openSetting();
                }
              }
            });
            reject(new Error('位置权限被拒绝'));
          } else {
            reject(new Error('获取位置失败'));
          }
        }
      });
    });
  }

  /**
   * 打开地图查看位置
   * @param location 位置信息
   */
  static openLocation(location: LocationInfo): Promise<void> {
    return new Promise((resolve, reject) => {
      wx.openLocation({
        latitude: location.latitude,
        longitude: location.longitude,
        name: location.name,
        address: location.address,
        scale: 16,
        success: () => {
          console.log('打开地图成功');
          resolve();
        },
        fail: (err) => {
          console.error('打开地图失败:', err);
          wx.showToast({
            title: '打开地图失败',
            icon: 'none'
          });
          reject(err);
        }
      });
    });
  }

  /**
   * 逆地址解析（坐标转地址）
   * @param latitude 纬度
   * @param longitude 经度
   * @returns Promise<LocationInfo>
   */
  static reverseGeocode(latitude: number, longitude: number): Promise<LocationInfo> {
    return new Promise((resolve, reject) => {
      wx.request({
        url: `${TENCENT_MAP_CONFIG.baseUrl}/ws/geocoder/v1/`,
        data: {
          location: `${latitude},${longitude}`,
          key: TENCENT_MAP_CONFIG.key,
          get_poi: 1
        },
        success: (res: any) => {
          console.log('逆地址解析响应:', res.data);
          
          if (res.data.status === 0) {
            const result = res.data.result;
            const addressComponent = result.address_component;
            
            const locationInfo: LocationInfo = {
              name: result.formatted_addresses?.recommend || '',
              address: result.address,
              latitude: latitude,
              longitude: longitude,
              province: addressComponent.province,
              city: addressComponent.city,
              district: addressComponent.district
            };
            
            resolve(locationInfo);
          } else {
            console.warn('腾讯地图API未开启WebService功能，使用降级方案');
            // 降级方案：返回基本的位置信息
            const locationInfo: LocationInfo = {
              name: '当前位置',
              address: `纬度:${latitude}, 经度:${longitude}`,
              latitude: latitude,
              longitude: longitude
            };
            resolve(locationInfo);
          }
        },
        fail: (err) => {
          console.error('逆地址解析请求失败:', err);
          // 降级方案：返回基本的位置信息
          const locationInfo: LocationInfo = {
            name: '当前位置',
            address: `纬度:${latitude}, 经度:${longitude}`,
            latitude: latitude,
            longitude: longitude
          };
          resolve(locationInfo);
        }
      });
    });
  }

  /**
   * 地址解析（地址转坐标）
   * @param address 地址字符串
   * @returns Promise<LocationInfo>
   */
  static geocode(address: string): Promise<LocationInfo> {
    return new Promise((resolve, reject) => {
      wx.request({
        url: `${TENCENT_MAP_CONFIG.baseUrl}/ws/geocoder/v1/`,
        data: {
          address: address,
          key: TENCENT_MAP_CONFIG.key
        },
        success: (res: any) => {
          console.log('地址解析响应:', res.data);
          
          if (res.data.status === 0) {
            const result = res.data.result;
            const location = result.location;
            const addressComponent = result.address_component;
            
            const locationInfo: LocationInfo = {
              name: address,
              address: result.formatted_addresses?.recommend || address,
              latitude: location.lat,
              longitude: location.lng,
              province: addressComponent.province,
              city: addressComponent.city,
              district: addressComponent.district
            };
            
            resolve(locationInfo);
          } else {
            console.error('地址解析失败:', res.data.message);
            reject(new Error(res.data.message || '地址解析失败'));
          }
        },
        fail: (err) => {
          console.error('地址解析请求失败:', err);
          reject(new Error('网络请求失败'));
        }
      });
    });
  }

  /**
   * 计算两点间距离（单位：米）
   * @param lat1 点1纬度
   * @param lng1 点1经度
   * @param lat2 点2纬度
   * @param lng2 点2经度
   * @returns 距离（米）
   */
  static calculateDistance(lat1: number, lng1: number, lat2: number, lng2: number): number {
    const R = 6371000; // 地球半径（米）
    const dLat = this.toRadians(lat2 - lat1);
    const dLng = this.toRadians(lng2 - lng1);
    const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
              Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) *
              Math.sin(dLng / 2) * Math.sin(dLng / 2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
  }

  /**
   * 角度转弧度
   */
  private static toRadians(degrees: number): number {
    return degrees * (Math.PI / 180);
  }

  /**
   * 验证坐标是否有效
   * @param latitude 纬度
   * @param longitude 经度
   * @returns boolean
   */
  static isValidCoordinate(latitude: number, longitude: number): boolean {
    return latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
  }

  /**
   * 格式化坐标显示
   * @param latitude 纬度
   * @param longitude 经度
   * @param precision 精度（小数位数）
   * @returns 格式化的坐标字符串
   */
  static formatCoordinate(latitude: number, longitude: number, precision: number = 6): string {
    return `${latitude.toFixed(precision)}, ${longitude.toFixed(precision)}`;
  }
}

/**
 * 地图选择组件的增强功能
 */
export class MapSelector {
  
  /**
   * 智能位置选择
   * 1. 先尝试获取当前位置作为地图中心
   * 2. 然后打开位置选择器
   * @returns Promise<LocationInfo>
   */
  static smartChooseLocation(): Promise<LocationInfo> {
    return new Promise(async (resolve, reject) => {
      try {
        // 先尝试获取当前位置
        const currentLocation = await LocationHelper.getCurrentLocation();
        
        // 使用当前位置作为地图中心打开选择器
        const selectedLocation = await LocationHelper.chooseLocation({
          latitude: currentLocation.latitude,
          longitude: currentLocation.longitude
        });
        
        resolve(selectedLocation);
      } catch (error) {
        // 如果获取当前位置失败，直接打开选择器
        try {
          const selectedLocation = await LocationHelper.chooseLocation();
          resolve(selectedLocation);
        } catch (chooseError) {
          reject(chooseError);
        }
      }
    });
  }

  /**
   * 位置选择器（带确认对话框）
   * @param currentLocation 当前已选位置
   * @returns Promise<LocationInfo>
   */
  static chooseLocationWithConfirm(currentLocation?: LocationInfo): Promise<LocationInfo> {
    return new Promise(async (resolve, reject) => {
      try {
        const options = currentLocation ? {
          latitude: currentLocation.latitude,
          longitude: currentLocation.longitude
        } : undefined;

        const selectedLocation = await LocationHelper.chooseLocation(options);
        
        // 显示确认对话框
        wx.showModal({
          title: '确认地址',
          content: `您选择的地址是：\n${selectedLocation.address}\n${selectedLocation.name}`,
          confirmText: '确认',
          cancelText: '重新选择',
          success: (res) => {
            if (res.confirm) {
              resolve(selectedLocation);
            } else {
              // 用户选择重新选择，递归调用
              this.chooseLocationWithConfirm(currentLocation)
                .then(resolve)
                .catch(reject);
            }
          }
        });
      } catch (error) {
        reject(error);
      }
    });
  }

  /**
   * 地址搜索选择器
   * @param keyword 搜索关键词
   * @param region 搜索区域（可选）
   * @returns Promise<LocationInfo[]>
   */
  static searchLocation(keyword: string, region?: string): Promise<LocationInfo[]> {
    return new Promise((resolve, reject) => {
      if (!keyword || keyword.trim() === '') {
        reject(new Error('搜索关键词不能为空'));
        return;
      }

      wx.request({
        url: `${TENCENT_MAP_CONFIG.baseUrl}/ws/place/v1/search`,
        data: {
          keyword: keyword.trim(),
          boundary: region ? `region(${region},0)` : 'region(全国,0)',
          key: TENCENT_MAP_CONFIG.key,
          page_size: 20,
          page_index: 1
        },
        success: (res: any) => {
          console.log('地址搜索响应:', res.data);
          
          if (res.data.status === 0 && res.data.data) {
            const locations: LocationInfo[] = res.data.data.map((item: any) => ({
              name: item.title,
              address: item.address,
              latitude: item.location.lat,
              longitude: item.location.lng,
              province: item.ad_info?.province || '',
              city: item.ad_info?.city || '',
              district: item.ad_info?.district || ''
            }));
            resolve(locations);
          } else {
            console.warn('腾讯地图搜索API未开启或无结果，提示用户使用地图选点');
            // 降级方案：提示用户使用地图选点
            wx.showModal({
              title: '搜索功能暂不可用',
              content: '地址搜索功能需要开启腾讯地图WebService API，建议使用"地图选点"功能',
              showCancel: false,
              confirmText: '知道了'
            });
            resolve([]);
          }
        },
        fail: (err) => {
          console.error('地址搜索请求失败:', err);
          // 降级方案：提示用户使用其他方式
          wx.showModal({
            title: '搜索失败',
            content: '网络连接失败，建议使用"地图选点"或"当前位置"功能',
            showCancel: false,
            confirmText: '知道了'
          });
          resolve([]);
        }
      });
    });
  }
}

/**
 * 地址输入组件增强功能
 */
export class AddressInput {
  
  /**
   * 创建地址选择按钮的点击处理
   * @param callback 选择完成回调
   * @param currentLocation 当前位置
   */
  static createLocationSelector(
    callback: (location: LocationInfo) => void,
    currentLocation?: LocationInfo
  ) {
    return async () => {
      try {
        wx.showLoading({
          title: '正在打开地图...'
        });

        const location = await MapSelector.smartChooseLocation();
        
        wx.hideLoading();
        
        // 显示选择结果
        wx.showToast({
          title: '地址选择成功',
          icon: 'success',
          duration: 1500
        });
        
        callback(location);
      } catch (error) {
        wx.hideLoading();
        
        let errorMsg = '选择地址失败';
        if (error instanceof Error) {
          if (error.message.includes('取消')) {
            return; // 用户取消，不显示错误
          }
          errorMsg = error.message;
        }
        
        wx.showToast({
          title: errorMsg,
          icon: 'none'
        });
      }
    };
  }

  /**
   * 验证地址信息是否完整
   * @param location 位置信息
   * @returns boolean
   */
  static validateLocation(location: LocationInfo): boolean {
    if (!location.address || location.address.trim() === '') {
      wx.showToast({
        title: '请选择详细地址',
        icon: 'none'
      });
      return false;
    }

    if (!LocationHelper.isValidCoordinate(location.latitude, location.longitude)) {
      wx.showToast({
        title: '位置坐标无效',
        icon: 'none'
      });
      return false;
    }

    return true;
  }

  /**
   * 格式化地址显示
   * @param location 位置信息
   * @param maxLength 最大显示长度
   * @returns 格式化后的地址字符串
   */
  static formatAddressDisplay(location: LocationInfo, maxLength: number = 50): string {
    let displayText = location.address;
    
    if (location.name && location.name !== location.address) {
      displayText = `${location.address} (${location.name})`;
    }
    
    if (displayText.length > maxLength) {
      displayText = displayText.substring(0, maxLength - 3) + '...';
    }
    
    return displayText;
  }
}

// 导出工具类
export { LocationHelper, MapSelector, AddressInput };

// 默认导出
export default {
  LocationHelper,
  MapSelector,
  AddressInput
};
